這篇的內容會相當豐富,因為會同時介紹 HERE 的三個地圖服務:
準備好了嗎?開始嘍!
前面介紹過了 Custom Locations、Geofencing,這次要來介紹的 HERE Custom Routes,後台也是在 Custom Locations,但功能更強大,可以用來自己建立自己的路網,並且規劃路徑。一般而言這種需求是用在特定的場地,更可能是封閉的場地,例如私有土地上的私有道路,例如工廠、機場、碼頭、礦場、農場等等,這樣的區域通常不允許外車進入,或是屬於機密性的區域,不希望內部的設施被外流,因此建置標準的導航圖資有困難,使用 Custom Routes 就可以自己建立自己的地圖,並且與外界的一般道路相連,這樣搭配 HERE SDK 製作導航 APP 就可以作到無縫的導引。
但除了上面提到的這個特定場地的用途之,Custom Routes 也可以用來覆蓋既有的的 HERE 路網屬性,例如我可以把某一條道路、橋樑、巷弄設定成禁止通行,或是加上額外的通行限制,例如把某一條道路設定成卡車禁行等等。這種用途就比較偏向於動態的物流用途,例如物流的控制中心可以把特定的道路用 Custom Routes 封閉掉,這樣算出來的路徑就會繞過這條道路。
而 HERE Custom Routes 除了可以在 Custom Locations 上面自己建立路網之外,還可以支援除了標準的車種(汽車、卡車、自行車、機車、行人)之外的自訂車種。
但是,如果您對導航圖資有概念的話,就會知道導航圖資背後的屬性非常複雜,例如道路等級、平均速度、車道數、通行方向、道路種類、轉彎限制等等,多達數十種屬性必須被考慮,光熟悉這數十種屬性就需要很長的時間,如果真的要從頭把路網建立出來,並且全部手動把屬性加上去,談何容易?所幸 HERE Custom Routes 也考慮到這一點了,當使用者建立自己的路網時,不需要一一列舉出每一種屬性,有需要的再列出即可,例如一般而言我們會指定這三個最重要的屬性:通行方向、車種、道路名稱。
最後值得一提的是,HERE Custom Routes 上面的路網與 Custom Locations 裡面的資料都是一樣受到完整的隱私權保護,每個使用者在上面建立的路網都不會被其他人使用或查閱。
※ HERE Custom Routes 官方網站:https://developer.here.com/documentation/custom-routing-extension/
我們還是使用 QGIS 來體驗一下建立自己的路網。首先打開 QGIS,把 OpenStreetMap 加入成底圖。如果您有看過之前的教學文章,這樣的操作您應該已經不陌生。
畫自己的地圖之前,您可以決定是要製作一個完整的封閉區域,或是可以跟外界路網連接的區域。如果要製作完整的封閉區域,不需要與外界道路連接的話,當然製作起來會簡單許多;不過如果您想製作的是可以跟一般道路相連結的話,就會需要知道 HERE 怎麼繪製這些道路。
您應該已經想到,我要怎麼確保我自己繪製的道路跟 HERE 的路網完美的接合呢?雖然 Custom Routes 有容許 5 公尺的誤差值,也就是說,如果你的路網跟 HERE 的路網雖然沒有真的接合在一起,但只要距離少於 5 公尺,HERE Routes 就會判定您有接合路網的意圖,而把它們連接在一起。
而 5 公尺在地圖上要怎麼抓,其實有點困難,因為網路地圖在繪製的時候會把線條加上寬度,而且底圖是開放街圖 OpenStreetMap,跟 HERE 的道路形狀可能還是略有不同,我這邊就要教你怎麼在地圖上看到 HERE 地圖真實的道路形狀,藉此我們可以盡可能的作到精確的接合路網,以減少不必要的錯誤。
※ HERE Vector Tile 官方網站:https://developer.here.com/documentation/vector-tiles-api/
Vector Tile 向量圖磚使用在網路地圖上,主要是這一兩年大行其道(但其實在導航機上面已經行之有年)。Google Map 其實蠻早就導入了這個技術,但沒有公開原始碼;之後 Mapbox 也提出了自己的向量圖磚規格,並且開放原始碼,因此目前市面上大部分的地圖服務供應商,例如 Mapbox、HERE、TomTom、Mapzen、ESRI 等等都是使用 Mapbox 的向量圖磚規格。
一般而言向量圖磚不太會單獨使用,通常會搭配地圖框架作為一個完整的底圖來使用,例如 HERE 與 Mapbox 都有自己的 JavaScript API/SDK,另外也有開放原始碼的 Tangram/Leaflet 等地圖框架可以使用。如果您有興趣的話,也可以自行研究。
然而,QGIS 除了可以把 PNG 圖磚(例如 OpenStreetMap)疊成底圖之外,也可以把 Mapbox 規格的向量圖磚加到地圖中。請在畫面左邊找到「Vector Tiles」,按下右鍵,選擇「New Connection...」。
接著出現了一個新增向量圖磚連線的對話框,有幾個欄位:
HERE Vector Tile
」https://vector.hereapi.com/v2/vectortiles/base/mc/{z}/{x}/{y}/omv?apikey=YOUR_API_KEY
,請把「YOUR_API_KEY」換成您自己的 HERE API KEY 就可以了。0
」17
」接著按下「OK」就可以了。
接著您就會在 Vector 下方看到您剛剛新增的「HERE Vector Tile」,請在上面點兩下,接著您就可以看到地圖上多疊了一層圖層上去。
把地圖放大之後,就會看到一些點、線、面在地圖上。這就是解碼後的 HERE Vector Tile 向量圖磚
您也可以使用「Identify Features」工具在 HERE 向量圖磚圖層上面,查詢向量圖磚的內容。
點選「Identify Features」工具之後,游標會變成黑色旁邊帶一個「i」的圖樣,接著在地圖上面隨意的點選,就會在畫面右側顯示出這個點、線、面圖徵的相關屬性。不過這些屬性相對比較複雜,您可以參閱 HERE 的說明文件。
不過地圖上這樣有點眼花撩亂,畢竟我們只需要道路線就好了,因此請在 HERE 向量圖磚的圖層上面按下右鍵,選擇「Properties...」
接著在左邊的「Symbology」分頁,把「Polygons」與「Points」都取消勾選,接著按下「OK」就可以了。
這樣地圖畫面簡潔許多,我們這樣同時可以看到 OpenStreetMap 的底圖,以及 HERE 的道路向量線。
到這邊事前準備已經完成了,接著我們可以開始來製作自己的路網。
我們這次要實做的地點是位於新北市八里區的台北港, WGS 84 經緯度為 121.381994,25.163374
(經度在前),ESPG:3857 座標為 13512637.0,2896015.7
(X 座標在前)。
因為您已經把 OpenStreetMap 加到地圖中,因此地圖座標系會自動轉成 ESPG:3857,請把「13512637.0,2896015.7」貼到 QGIS 視窗下方的 Coordonate 文字框,並按下「Enter」,就會移動到台北港的位置。
在這邊可以看到,HERE 並沒有收錄台北港貨櫃儲運中心的道路,因為這裡並不是公共道路,而是港區內,一般人無法進入的區域。當然您也可以在 Map Creator 網站上面把這些道路畫上去(HERE 公司向您致上最高敬意),不過這不是我們這次的目的,我們的目的是要把台北港內的道路做成一個私有的路網,因此不會被公共對象所使用。
點選 QGIS 功能表的「Layer」->「Create Layer」->「New Shapefile Layer...」,
接著請把這個 Shapefile 指定到您偏好的位置,但是「Geometry type」請選取「Line」,因為我們要做的是道路,道路是線型的圖徵。
然後在 New Field 這邊新增一個欄位叫做「TD
」,代表行駛方向。其實 Custom Routes 支援的行駛方向欄位名稱叫做「TRAVEL_DIRECTION
」,不過因為 Shapefile 欄位名稱有字串長度的限制,因此目前就先用 TD
來表示,之後我們在上傳前會需要改成 TRAVEL_DIRECTION
。
我們先複習一下在 快速建構地圖服務(十一)- HERE Route Matching GPS 軌跡分析 所提過的:
在 HERE 地圖中,所有的道路都屬於「線」,而一個線段一定會有兩端,HERE 的定義中,兩個點之間位在南邊的就叫做 Reference Node(參考點),而另一個點就叫做 Non-reference Node(非參考點)。而有了參考點之後,就可以用參考點來表示道路的方向,例如:
- 從 Reference Node 到 Non-reference Node,稱為順向(Positive Direction),又稱為 From Ref。
- 從 Non-reference Node 到 Reference Node,稱為逆向(Negative Direction),又稱為 To Ref。
因此,在 HERE 表示道路行駛方向的 TRAVEL_DIRECTION 欄位,會有三個可能的值:
而所謂的順向逆向,是要以位在南邊的 Reference Node(參考點)為準,這點請務必記得了!
至於為什麼新增行駛方向這個欄位,因為這是最重要的,如果您有興趣的話,也可以研究說明文件來新增其他欄位,但行駛方向通常是必備的一個屬性。
完成後按下「OK」,就完成了圖層的新增。接著請開啟編輯模式,在剛剛新增的圖層上面按下右鍵,選擇「Toggle Editing」。
接著使用滑鼠滾輪把地圖畫面放大,您會看到 OpenStreetMap 已經標明方向性了。
我們先找到接合的入口,您可以改變 HERE 向量圖磚的線條風格來讓線條更醒目。決定了接合的入口之後,請選取功能表的「View」->「Toolbars」->「Snapping Toolbar」來開啟黏附工具列。
接著找到工具列的 U 型磁鐵圖案,點下去開啟黏附功能。
接著按下工具列的「Add Line Feature」來準備開始畫線。
這時候游標會變成十字瞄準線,對準 HERE 向量圖磚上面的道路末端,接著畫出第一條線。在數化地圖的時候,建議每到一個交叉口,就做一個斷點,避免不必要的交集問題。
抵達第一個路口之後,請按下左鍵,接著按下右鍵來結束這個線段。
按下右鍵之後會出現一個對話框,請在「TD」這個欄位輸入「B
」,代表雙向。接著按下「OK」結束這個線段的編輯。
但是線段真的太細了,我們改粗一點,然後繼續我們的第二個線段。我們把滑鼠移到前一個線段的尾端,會發現出現了一個紫色的方框,這代表我們已經開啟的黏附功能會讓下一個線段的起點接合在既有的線段端點,這樣可以確保線段之間完美的接合。
結束這個線段之後,我們給它的「TD」是「F
」,代表順向(由南到北),完成後就按下「Enter」。
如果是彎曲的道路,我們就必須沿著道路形狀按下左鍵,代表一個又一個的形狀點,到道路的交叉點之後按下右鍵完成這個線段。
※ 在數化的過程中,可以按下滑鼠的中鍵(滾輪)來移動地圖,搭配滾輪進行縮小、放大的動作,非常的順手。
然後我們就可以一個又一個線段的完成我們的地圖製作,時間其實不需要太久,這個區域花了 12 分鐘就數化完畢。
完成後,我們可以設定我們繪圖的圖層使用「TD」屬性來顯示,我們就可以檢驗我們設定的行駛方向是否正確。
在圖層上面按下右鍵選擇「Properties...」之後選擇「Symbology」,然後在上方選擇「Categorized」,在「Value」輸入「TD」,接著按下下方的「Classify」,就會依照我們輸入的 B/F/T 三個值畫成不同的顏色。
完成後像這樣,我們就可以很方便的檢驗我們輸入的行駛方向是否正確。如果發現我們有某個線段輸入錯誤了,也會很容易發現。
如果發現有錯誤的線段,請按下工具列的「Select Features by area or single click」,這個工具列可以用框選的方式或單點的方式來選取我們圖層上面的圖徵。
接著請在我們想要修正的線段上面按下去,這個線段會變成淺黃色代表正在被選取的狀態。
接著按下工具列中,位於紅色垃圾桶左側的屬性編輯按鈕。
然後把屬性改成正確的,按下「OK」就好。
接著確認無誤後,關閉編輯狀態。
再次使用「Toggle Editing」來關閉編輯狀態。
這時後會出現一個對話框問您要不要存檔,請按下「Save」來儲存我們繪圖的結果到 Shapefile。
這樣就完成了繪圖的部份。接著我們把我們繪製完成的 Shapefile 儲存成 CSV。請依照之前的課程教學過的部份,存成含有 WKT 欄位的 CSV 檔。
記得「Geometry type」要選擇「LineString」,其他的都跟之前的課程一樣。
接著我們檢視剛剛儲存的 CSV 檔,確認 WKT 欄位輸出無誤。
繪圖的部份到這邊就結束了,您可以關閉 QGIS,進行以下的步驟。
我們之前介紹過的 Custom Locations,您可能會注意到,我們上傳的都是一個一個 Layer(圖層),但是在 Custom Routes 雖然也是使用 Custom Locations 來儲存資料,但路徑規劃需要的屬性相當多,不是一個圖層就可以表現的,因此我們上傳的單位從 Layer(圖層)變成了 Map(地圖)。Custom Routes 上傳的地圖資料會轉換成不同的 Layer,儲存在 Custom Locations 中。
也因為上傳的方式與 Custom Locations 不同,因此我們也很無法使用之前介紹過的網頁版上傳,也很難使用 Postman 直接上傳,因為上傳的格式也不是我們之前介紹過的 WKT 文件。
因此我這邊寫了一個 Python 3.x 的小程式來把我們剛剛輸出的 CSV 檔,轉換成 Custom Routes 需要的格式。請把「wkt_file_path」這個變數的內容改成您剛剛輸出的 CSV 檔的完整路徑。並且把原始的 CSV 檔的欄位名稱「TD」改成「TRAVEL_DIRECTION」,否則上傳會失敗。
修改後的 CSV 檔會像這樣:
以下就是程式碼:
import csv
import json
import os
wkt_file_path = 'C:\\Users\\guanlwu\\Downloads\\temp\\taipeiport.csv' # Your input wkt file path
with open(wkt_file_path, mode='r') as wkt_file:
reader = csv.DictReader(wkt_file, delimiter='\t')
overlay_spec = []
for row in reader:
shape = []
data = {}
for key in row.keys():
if key != 'WKT' and key != 'id':
data[key] = row[key]
geom_list = row['WKT'].replace('MULTILINESTRING ((', '').replace('))', '').split(',')
for geom in geom_list:
geom = geom.split(' ')
lat = float(geom[1])
lng = float(geom[0])
shape.append([lat, lng])
overlay_spec.append({'op': 'create',
'shape': shape,
'data': data})
overlay_spec = json.dumps(overlay_spec).replace(' ', '')
output = open(os.path.join(os.path.dirname(wkt_file_path), 'output.txt'), 'w')
output.write(overlay_spec)
執行完之後,在 CSV 檔的同一個資料夾之下會新增一個「output.txt」,裡面打開就是轉換完成的 JSON 字串。
裡面您可以看到幾個屬性:
接著我們打開 Postman,新增一個 POST request,在網址列中填入「https://fleet.ls.hereapi.com/2/overlays/upload.json
」,並在「Params」新增一個參數,Key 為「apiKey」,Value 為您自己的 HERE API KEY。
接著切換到「Body」,接著選擇「form-data」,然後輸入三個 Key/Value:
確認無誤後,就可以按下「Send」送出 request。
如果您看到類似以下的回傳,就代表成功了!所以在這邊您可以看到,您剛剛上傳的「OVERLAYTAIPEIPORT」這張地圖,裡面有四個圖層,分別是:
這些屬性如果沒有特別指定的話,就會從自建路網跟 HERE 既有地圖連接的道路繼承過來,例如我們剛剛沒有指定道路的 Functional Class,但如果連接的道路是 Functional Class 是 5,您自建的路網就也會是 5;如果連接的道路只限機車可以行駛,那您自建的路網也會有相同的限制。
{
"layers": [
"LINK_FC5",
"ROAD_ADMIN_FC5",
"ROAD_GEOM_FC5",
"LINK_ATTRIBUTE_FC5"
],
"meta": [
{
"layerId": "LINK_FC5",
"lastUpdateTimeStamp": 1601968741589
},
{
"layerId": "ROAD_ADMIN_FC5",
"lastUpdateTimeStamp": 1601968741603
},
{
"layerId": "ROAD_GEOM_FC5",
"lastUpdateTimeStamp": 1601968741617
},
{
"layerId": "LINK_ATTRIBUTE_FC5",
"lastUpdateTimeStamp": 1601968741635
}
],
"response_code": "201 Created"
}
到這邊,自建路網就完成了!
我們現在就來測試看看使用我們自建的路網進行路徑規劃。我們可以規劃一個從既有道路到我們自建路網的路徑。
我們可以開啟 QGIS 來取得經緯度。例如我們的出發點可以選在八里左岸碼頭附近(經度:121.4294844,緯度:25.1599944)。
結束點選在我們自建路網上(經度:121.38074623,緯度:25.16081350)
然後我們開啟 Postman,新增一個 GET request,並填入以下資訊:
https://fleet.ls.hereapi.com/2/calculateroute.json
25.1599944,121.4294844
)25.16081350,121.38074623
)fastest;car
)OVERLAYTAIPEIPORT
)readonly
shape
)確認無誤後就可以按下「Send」,來送出請求。如果收到類似這樣的回傳,就代表成功了。
不過我們這樣看文字實在很難確定是不是真的成功了,因此我們要把路徑顯示在圖面上。
HERE Map Image API 的用途很簡單,就是依照您送出的請求,來回傳一張靜態地圖影像。我們可以用這個 API 來把剛剛算出來的路線圖畫在地圖上,這樣我們可以很快速的驗證自建路網是不是真的成功了。
※ HERE Map Image API 官方網站:https://developer.here.com/documentation/map-image/
請打開 Postman,找到我們剛剛取得的路徑規劃回傳,接著選擇「Raw」來檢視純文字模式(原本是 Pretty 模式比較容易閱讀)。
接著找到回傳資訊的末端的「Shape」屬性,後面是一長串的經緯度,請把這串經緯度,不包含前後的括號,複製起來備用。
例如以下的字串:
25.15999,121.42954,25.15934,121.42944,25.15898,121.42938,25.15913,121.42872,25.15924,121.42823,25.15934,121.42775,25.15938,121.42756,25.15944,121.4273,25.15948,121.42711,25.15951,121.42693,25.15953,121.42676,25.15954,121.42655,25.15953,121.42635,25.15952,121.42621,25.1595,121.42608,25.15947,121.42595,25.15939,121.42563,25.15933,121.42539,25.15926,121.42513,25.15915,121.4247,25.15911,121.42456,25.15901,121.42417,25.15894,121.42388,25.1589,121.42372,25.15887,121.42362,25.15884,121.42353,25.15879,121.4234,25.15873,121.42327,25.1586,121.42299,25.15846,121.42272,25.15831,121.4224,25.15812,121.42198,25.15777,121.42126,25.15751,121.42073,25.1574,121.42052,25.15717,121.42,25.15693,121.41949,25.15673,121.41907,25.15657,121.41874,25.1564,121.41838,25.15622,121.418,25.15605,121.41764,25.15589,121.41732,25.15573,121.41699,25.15534,121.41614,25.15513,121.4157,25.15496,121.41537,25.15471,121.41485,25.1546,121.4146,25.15446,121.41431,25.15431,121.41401,25.15419,121.41375,25.15407,121.4135,25.15398,121.4133,25.15385,121.41303,25.15372,121.41276,25.15361,121.41253,25.15343,121.41215,25.15322,121.41168,25.15278,121.4108,25.1525,121.41021,25.15229,121.40976,25.15214,121.40944,25.15187,121.40887,25.15179,121.4087,25.15163,121.40835,25.15247,121.40739,25.15291,121.40687,25.15328,121.40645,25.15444,121.40513,25.15531,121.40417,25.15437,121.40307,25.15489,121.40251,25.15566,121.40168,25.1559,121.40143,25.15672,121.40058,25.15795,121.40193,25.15813,121.40208,25.1582,121.40214,25.15844,121.40223,25.16154,121.39873,25.16198,121.39814,25.16559,121.39398,25.1679,121.39124,25.16873,121.39031,25.16867,121.39012,25.16791,121.38844,25.1679,121.38791,25.16777,121.38762,25.16649,121.38468,25.1652,121.38174,25.16394,121.37887,25.16312,121.3793,25.16262,121.37957,25.16214,121.37982,25.16167,121.38006,25.1612,121.38031,25.16076,121.38054,25.16096,121.381
接著新增一個 GET request,並填入以下資訊:
https://image.maps.ls.hereapi.com/mia/1.6/route
1280
)720
)cht
)png
)25.15999,121.42954,25.16096,121.381
)3
)320
)接著按下「Send」來送出請求,回傳的圖片就會繪製整個路徑在地圖上,可以看到路徑從八里左岸碼頭一路經過道路抵達了台北港之內的終點。
如果其他人使用 HERE Routing API 的路徑規劃功能,就沒辦法抵達指定的終點,因為這部份的路網是您自己建立的,因此不會存在於 HERE 地圖中,更不會被其他人使用到,因此就確保了您自己建立的路網只能被您自己使用。
以上就完成了一個自建路網加上私有路徑規劃的使用場景。值得一提的就是,HERE SDK 也支援私有路徑規劃,因此您可以部署您的路網在 Custom Routes,並且使用 HERE SDK 開發手機 APP 來使用您的自建路網。
到這邊 Custom Locations、Geofencing、Custom Routes 三兄弟的介紹就完成了,您可以到 HERE 開發者網站 查閱這些地圖服務的詳細說明文件,來規劃您的地圖服務。
快速建構地圖服務(一) - 認識 HERE Studio / Data Hub
快速建構地圖服務(二) - 認識 HERE Data Hub CLI / API
快速建構地圖服務(三) - 使用 QGIS 玩轉 HERE Data Hub
快速建構地圖服務(四) - 當 Leaflet JS 遇見 Data Hub
快速建構地圖服務(五) - 整合 HERE 地點搜尋 API
快速建構地圖服務(六)- HERE Waypoints Sequence 路徑最佳排序
快速建構地圖服務(七)- 認識 HERE Routing API - 路徑規劃
快速建構地圖服務(八)- 認識 Matrix Routing
快速建構地圖服務(九)- Isoline Routing
快速建構地圖服務(十)- HERE Tour Planning 物流路徑預排與成本精算
快速建構地圖服務(十一)- HERE Route Matching GPS 軌跡分析
快速建構地圖服務(十二)- HERE Custom Locations 地圖資料倉儲與查詢
快速建構地圖服務(十三)- HERE Geofencing 地理圍籬
快速建構地圖服務(十四)- HERE Custom Routes 自建路網 + Vector Tile 向量圖磚 + Map Image API 靜態地圖
快速建構地圖服務(十五)- HERE Positioning 網路定位服務